<?php

namespace
{
    define('EXT', '.php');
}

namespace System\Core
{

    use \System\Types;

require_once \SYSPATH . 'Types/Object.php';
    require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Engineer.php';
    require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Controller.php';
    require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Model.php';
    require_once __DIR__ . \DIRECTORY_SEPARATOR . 'View.php';
    require_once \SYSPATH . 'Lib' . \DIRECTORY_SEPARATOR . 'MasterPage.php';
    require_once __DIR__ . \DIRECTORY_SEPARATOR . 'Errors/Error.php';

    class Loader extends Types\Object
    {

        private $loaderPaths = array();
        private $loaders = array();

        /**
         * @var Loader
         */
        private static $_instance;

        function __construct()
        {
            parent::__construct();

            $this->loaderPaths[] = \SYSPATH . '..' . DIRECTORY_SEPARATOR;

            \spl_autoload_register(array($this, '__autoload'));
        }

        private function __autoload($object)
        {

            $completion = \str_replace('\\', \DIRECTORY_SEPARATOR, $object);
            $completion = \str_replace('/', \DIRECTORY_SEPARATOR, $completion);

            if (!\class_exists($object) && !\interface_exists($object))
            {
                foreach ($this->loaderPaths as $path)
                {
                    if (!$path)
                        continue;

                    $ph = $path;
                    $ph .= (!\preg_match('/^(.*)(\\|\/)$/i', $path)) ? \DIRECTORY_SEPARATOR : '';
                    $ph = \str_replace('\\', \DIRECTORY_SEPARATOR, $ph);
                    $ph = \str_replace('/', \DIRECTORY_SEPARATOR, $ph);
                    $ph .= $completion . '.php';

                    if (\file_exists($ph) && !\is_dir($ph))
                        require_once $ph;
                }
            }

            if (\count($this->loaders) > 0)
            {
                foreach ($this->loaders as $loader)
                {
                    if (!$loader)
                        continue;

                    $loader($object);
                }
            }
        }

        public function RegisterLoader(\Closure $closure)
        {
            $index = \count($this->loaders);

            $this->loaders[] = $closure;

            return $index;
        }

        public function UnregisterLoader($index)
        {
            $indexer = \count($this->loaders);

            $closure = $this->loaders[$index];

            if ($indexer > $index)
                $this->loaders[$index] = function()
                        {
                            return;
                        };

            return $closure;
        }

        /**
         * @return \System\Core\Loader
         */
        public static function &GetInstance()
        {
            if (!self::$_instance)
                self::$_instance = new self();

            return self::$_instance;
        }

        public function AddPath($path)
        {
            $index = \count($this->loaderPaths);

            $this->loaderPaths[] = (string) $path;

            return $index;
        }

        public function RemovePath($index)
        {
            $path = $this->loaderPaths[$index];

            $this->loaderPaths[$index] = null;

            return $path;
        }

        public function Load($classname)
        {
            $this->__autoload($classname);
        }

        public function LoadFileContent($filename)
        {
            $buffer = @\file_get_contents($filename);

            if ($buffer === false)
                Errors\Error::ShowErr("O arquivo \"{$filename}\" não pode ser encontrado ou não permite a leitura do conteúdo.");

            return $buffer;
        }

    }

}
